package process

import (
	"code.project.com/chatroom/common/message"
	"code.project.com/chatroom/server/model"
	"code.project.com/chatroom/server/utils"
	"encoding/json"
	"fmt"
	"net"
)

// 用户消息相关的

// 用户的连接
type UserProcess struct {

	Conn net.Conn
	// 那个用户的连接
	userId int
}

// 编写通知所有在线的用户方法
// userId 通知替他用户我上线了
func (u *UserProcess)NotifyOtherOnlineUser(userId int)  {
	// 遍历 onlineUsers 然后发送 NotifyUserStatusMes
	for id, up := range userMgr.onlineUsers{
		if id == userId {
			continue
		}

		// 开始通知 [单独写一个通知其他]
		err := up.NotifyMeOnline(userId)
		if err != nil {
			fmt.Println("通知失败")
		}
	}
}

func (u *UserProcess) NotifyMeOnline(userId int) (err error){
	// 组装我们的NotifyUserStatusMes
	var mes message.Message
	mes.Type = message.NotifyUserMesType
	var notifyUserStatus message.NotifyUserStatusMes
	notifyUserStatus.UserId = userId
	notifyUserStatus.UserStatus = message.UserOnline

	// 2. 将 notifyUserStatus 序列化
	data, err := json.Marshal(notifyUserStatus)
	if err != nil {
		fmt.Println("notifyUserStatusMes json 序列化失败", err)
		return
	}

	// 将序列化后的notifyUserStatus 赋值给 mes.Data
	mes.Data = string(data)

	// 再次对mes 序列化
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("mes json 序列化失败", err)
		return
	}

	//厂家transfer 实例 发送状态
	tf := &utils.Transfer{
		Conn: u.Conn,
	}
	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println("发送失败")
		return
	}
	return



}

func (u *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {
	// 1. 先从mes中取出 mes.Data 并且直接反系列化registerMes
	var registerMes message.RegisterMes
	err = json.Unmarshal([]byte(mes.Data), &registerMes)
	if err != nil {
		fmt.Println("反序列化失败，err=", err)
	}

	// 2. 声明一个返回消息类型结构体 resMes
	var resMes message.Message
	resMes.Type = message.RegisterResType
	// 声明一个返回的内容的 LoginResMes
	var registerResMes message.RegisterResMsg

	// 3. 数库注册
	// 到redis数据库验证提交过来的
	err = model.MyUserDao.Register(&registerMes.User)
	if err != nil {
		if err == model.ERROR_USER_EXISTS {  // 用户存在
			registerResMes.Code = 505
			registerResMes.Error = err.Error()
		}else {
			registerResMes.Code = 506
			registerResMes.Error = "注册发生未知错误"
		}
	}else {
		registerResMes.Code = 200
		fmt.Println(registerMes.User,"注册成功")
	}

	data, err := json.Marshal(registerResMes)
	if err != nil {
		fmt.Println("注册成功信息反序列失败")
		return
	}

	resMes.Data = string(data)

	// 对 resMes 进行序列化 进行发送
	data, err = json.Marshal(resMes)
	if err != nil {
		fmt.Println("json Marshal failed err:= ", err)
		return
	}

	//  发送data 将其封装到writePkg
	tf := &utils.Transfer{
		Conn: u.Conn,
	}
	err = tf.WritePkg(data)
	return

}

// serverProcessLogin  出登录请求
func (u *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
	// 1. 先从mes中取出 mes.Data 并且直接反系列化LoginMes
	var loginMes message.LoginMes
	err = json.Unmarshal([]byte(mes.Data), &loginMes)
	if err != nil {
		fmt.Println("反序列化失败，err=", err)
	}

	// 2. 声明一个返回消息类型结构体 resMes
	var resMes message.Message
	resMes.Type = message.LoginReMesType
	// 声明一个返回的内容的 LoginResMes
	var loginResMes message.LoginReMsg

	// 到redis数据库验证提交过来的
	user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)

	if err != nil { // 用户验证失败

		if err == model.ERROR_USER_NOTEXISTS {
			loginResMes.Code = 500 // 表示该用户不存在
			loginResMes.Error = err.Error()
		} else if err == model.ERROR_USER_PWD {
			loginResMes.Code = 403
			loginResMes.Error = err.Error()
		} else {
			loginResMes.Code = 505
			loginResMes.Error = "服务器内部错误"
		}

	} else { // 登录成功
		loginResMes.Code = 200
		u.userId = loginMes.UserId
		userMgr.AddOnlineUser(u)  // 添加当前用户
		// 通知在线的用户 我上线了
		u.NotifyOtherOnlineUser(loginMes.UserId)
		// 将当前在线的用户id放入loginResMsg
		// 遍历userMgr.OnlineUsers

		for id,_ := range userMgr.onlineUsers{
			loginResMes.UsersId = append(loginResMes.UsersId,id)
		}
		fmt.Println(user, "登录成功")
	}

	// loginResMes 序列化
	data, err := json.Marshal(loginResMes)
	if err != nil {
		fmt.Println("json marshal failed err:= ", err)
		return
	}
	resMes.Data = string(data)

	// 对 resMes 进行序列化 进行发送
	data, err = json.Marshal(resMes)
	if err != nil {
		fmt.Println("json Marshal failed err:= ", err)
		return
	}

	//  发送data 将其封装到writePkg
	tf := &utils.Transfer{
		Conn: u.Conn,
	}
	err = tf.WritePkg(data)
	return
}


